diff -rcNP void-hardened-kernel 2/Documentation/admin-guide/kernel-parameters.txt void-hardened-kernel/Documentation/admin-guide/kernel-parameters.txt
*** void-hardened-kernel 2/Documentation/admin-guide/kernel-parameters.txt	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/Documentation/admin-guide/kernel-parameters.txt	2021-04-11 22:39:31.000000000 +0300
***************
*** 2689,2694 ****
--- 2689,2698 ----
  			log everything. Information is printed at KERN_DEBUG
  			so loglevel=8 may also need to be specified.
  
+ 	modharden=	[SECURITY]
+ 			on - Restrict module auto-loading to CAP_SYS_MODULE
+ 			off - Don't restrict module auto-loading
+ 
  	module.sig_enforce
  			[KNL] When CONFIG_MODULE_SIG is set, this means that
  			modules without (valid) signatures will fail to load.
diff -rcNP void-hardened-kernel 2/Documentation/admin-guide/sysctl/kernel.rst void-hardened-kernel/Documentation/admin-guide/sysctl/kernel.rst
*** void-hardened-kernel 2/Documentation/admin-guide/sysctl/kernel.rst	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/Documentation/admin-guide/sysctl/kernel.rst	2021-04-11 22:39:31.000000000 +0300
***************
*** 469,474 ****
--- 469,488 ----
  0, the cache is disabled. Enabled if nonzero.
  
  
+ modharden:
+ ==========
+ 
+ This toggle indicates whether unprivileged users are allowed to
+ auto-load kernel modules.
+ 
+ When modharden is set to (0) there are no restrictions. When
+ modharden is set to (1), only users with ``CAP_SYS_MODULE`` are
+ permitted to load kernel modules
+ 
+ The kernel config option ``CONFIG_SECURITY_MODHARDEN`` sets the
+ default value of modharden.
+ 
+ 
  modules_disabled:
  =================
  
diff -rcNP void-hardened-kernel 2/include/linux/kmod.h void-hardened-kernel/include/linux/kmod.h
*** void-hardened-kernel 2/include/linux/kmod.h	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/include/linux/kmod.h	2021-04-11 22:39:31.000000000 +0300
***************
*** 22,27 ****
--- 22,28 ----
   * usually useless though. */
  extern __printf(2, 3)
  int __request_module(bool wait, const char *name, ...);
+ extern int modharden;
  #define request_module(mod...) __request_module(true, mod)
  #define request_module_nowait(mod...) __request_module(false, mod)
  #define try_then_request_module(x, mod...) \
diff -rcNP void-hardened-kernel 2/kernel/kmod.c void-hardened-kernel/kernel/kmod.c
*** void-hardened-kernel 2/kernel/kmod.c	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/kernel/kmod.c	2021-04-11 22:39:31.000000000 +0300
***************
*** 106,111 ****
--- 106,128 ----
  	return -ENOMEM;
  }
  
+ int modharden __read_mostly = IS_ENABLED(CONFIG_SECURITY_MODHARDEN);
+ 
+ static int __init enable_modharden(char *level)
+ {
+ 	if (!level)
+ 		return -EINVAL;
+ 
+ 	if (strcmp(level, "on") == 0)
+ 		modharden = 1;
+ 	else if (strcmp(level, "off") == 0)
+ 		modharden = 0;
+ 	else
+ 		return -EINVAL;
+ 
+ 	return 0;
+ }
+ early_param("modharden", enable_modharden);
  /**
   * __request_module - try to load a kernel module
   * @wait: wait (or not) for the operation to complete
***************
*** 149,154 ****
--- 166,176 ----
  	if (ret)
  		return ret;
  
+ 	if (modharden && !capable(CAP_SYS_MODULE)) {
+ 		printk(KERN_ALERT "denied attempt to auto-load module %s\n", module_name);
+ 		return -EPERM;
+ 	}
+ 
  	if (atomic_dec_if_positive(&kmod_concurrent_max) < 0) {
  		pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...",
  				    atomic_read(&kmod_concurrent_max),
diff -rcNP void-hardened-kernel 2/kernel/sysctl.c void-hardened-kernel/kernel/sysctl.c
*** void-hardened-kernel 2/kernel/sysctl.c	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/kernel/sysctl.c	2021-04-11 22:39:31.000000000 +0300
***************
*** 730,735 ****
--- 730,744 ----
  		.extra1		= SYSCTL_ONE,
  		.extra2		= SYSCTL_ONE,
  	},
+ 	{
+ 	.procname	= "modharden",
+ 	.data		= &modharden,
+ 	.maxlen		= sizeof(int),
+ 	.mode		= 0644,
+ 	.proc_handler	= proc_dointvec_minmax,
+ 	.extra1		= SYSCTL_ZERO,
+ 	.extra2		= SYSCTL_ONE,
+ 	},
  #endif
  #ifdef CONFIG_UEVENT_HELPER
  	{
diff -rcNP void-hardened-kernel 2/security/Kconfig void-hardened-kernel/security/Kconfig
*** void-hardened-kernel 2/security/Kconfig	2021-04-08 00:01:58.000000000 +0300
--- void-hardened-kernel/security/Kconfig	2021-04-11 22:43:45.000000000 +0300
***************
*** 42,47 ****
--- 42,69 ----
  
  	  If you are unsure how to answer this question, answer N.
  
+ config SECURITY_MODHARDEN
+ 	bool "Harden module auto-loading"
+ 	default n
+ 	depends on MODULES
+   	help
+ 	  If you say Y here, module auto-loading in response to use of some
+ 	  feature implemented by an unloaded module will be restricted to
+ 	  CAP_SYS_MODULE. Enabling this option helps defend against attacks
+ 	  by unprivileged users who abuse the auto-loading behavior to
+ 	  cause a vulnerable module to load that is then exploited.
+ 
+ 	  If this option prevents a legitimate use of auto-loading for a
+ 	  non-root user, the administrator can execute modprobe manually
+ 	  with the exact name of the module mentioned in the alert log.
+ 	  Alternatively, the administrator can add the module to the list
+ 	  of modules loaded at boot by modifying init scripts.
+ 
+ 	  This setting can be overridden at runtime via the
+ 	  kernel.modharden sysctl.
+ 
+ 	  If unsure say N.
+ 
  config SECURITY
  	bool "Enable different security models"
  	depends on SYSFS
***************
*** 353,356 ****
  source "security/Kconfig.hardening"
  
  endmenu
- 
--- 375,377 ----
